<?PHP

class chess
{
    private $board = array();
    private $row;
    private $col;
    private $r;
    private $c;
    private $flag;   //true: 黑 false: 白
    private $quit = TRUE;

    public function init()
    {
        $this->r = (int)($this->row / 2);
        $this->c = (int)($this->col / 2);
        $this->flag = TRUE;

        for ($i = 0; $i < $this->row; ++$i) {
            for ($j = 0; $j < $this->col; ++$j) {
                $this->board[$i][$j] = '+';
            }
        }
    }

    public function __construct($row = 11, $col = 11)
    {
        $this->row = $row;
        $this->col = $col;

        $this->init();

        $this->show();
    }

    public function __get($name)
    {
        return $this->$name;
    }

    public function show()
    {
        printf("\033[1;1H");
        for ($i = 0; $i < $this->row; ++$i) {
            for ($j = 0; $j < $this->col; ++$j) {
                echo $this->board[$i][$j];
            }
            echo PHP_EOL;
        }
        printf("\033[%d;%dH", $this->r + 1, $this->c + 1);
    }

    private function checkWin($r_flag, $c_flag, $r_inc, $c_inc)
    {
        $ch = '*';
        $r = $this->r - 4 * $r_flag;
        $c = $this->c - 4 * $c_flag;

        /*
         * printf("\033[s\033[%d;1H\033[2Kx = %d, y = %d, r = %d, c = %d, r_flag = %d, c_flag = %d type = %s\033[u",
         *     $this->row + 1, $this->r, $this->c,
         *     $r, $c, $r_flag, $c_flag, gettype($r));
         */
        // fflush(STDOUT);
        // sleep(1);

        for ($i = 0; $i < 9; ++$i, $r += $r_inc, $c += $c_inc) {
            if ($r < 0 || $r >= $this->row
                    || $c < 0 || $c >= $this->col)
                continue;

            if ($ch === $this->board[$r][$c])
                $count++;
            else {
                $ch = $this->board[$r][$c];
                $count = 1;
            }
            if ($count == 5)
                return TRUE;
        }
        return FALSE;
    }

    public function __set($name, $value)
    {
        if ($name == 'r' || $name  == 'c')
        {
            $this->$name = $value;
        }
    }

    public function press()
    {
        // printf("r = %d, c = %d\n", $this->r, $this->c);
        if ($this->board[$this->r][$this->c] != '+')
            return 0;

        if ($this->flag)
            $this->board[$this->r][$this->c] = '#';
        else
            $this->board[$this->r][$this->c] = '@';

/*
 * {
 *         for ($i = 0, $ch = '*', $r = $this->r - 4; $i < 9; ++$i, $r++) {
 *             if ($r < 0 || $r >= $this->row)
 *                 continue;
 *
 *             if ($ch === $this->board[$r][$this->c])
 *                 $count++;
 *             else {
 *                 $ch = $this->board[$r][$this->c];
 *                 $count = 1;
 *             }
 *             if ($count == 5)
 *                 return 2;
 *         }
 *
 *         for ($i = 0, $ch = '*', $c = $this->c - 4; $i < 9; ++$i, $c++) {
 *             if ($c < 0 || $c >= $this->col)
 *                 continue;
 *
 *             if ($ch === $this->board[$this->r][$c])
 *                 $count++;
 *             else {
 *                 $ch = $this->board[$this->r][$c];
 *                 $count = 1;
 *             }
 *             if ($count == 5)
 *                 return 2;
 *         }
 *
 *         for ($i = 0, $ch = '*', $r = $this->r - 4, $c = $this->c - 4; $i < 9; ++$i, $r++, $c++) {
 *             if ($r< 0 || $r >= $this->row || $c < 0 || $c >= $this->col)
 *                 continue;
 *
 *             if ($ch === $this->board[$r][$c])
 *                 $count++;
 *             else {
 *                 $ch = $this->board[$r][$c];
 *                 $count = 1;
 *             }
 *             if ($count == 5)
 *                 return 2;
 *         }
 *
 *         for ($i = 0, $ch = '*', $r = $this->r - 4, $c = $this->c + 4; $i < 9; ++$i, $r++, $c--) {
 *             if ($r< 0 || $r >= $this->row || $c < 0 || $c >= $this->col)
 *                 continue;
 *
 *             if ($ch === $this->board[$r][$c])
 *                 $count++;
 *             else {
 *                 $ch = $this->board[$r][$c];
 *                 $count = 1;
 *             }
 *             if ($count == 5)
 *                 return 2;
 *         }
 * }
 */

        if ($this->checkWin(1, 0, 1, 0)
             || $this->checkWin(0, 1, 0, 1)
             || $this->checkWin(1, 1, 1, 1)
             || $this->checkWin(1, -1, 1, -1))
             return 2;

        for ($i = 0; $i < $this->row; ++$i) {
            for ($j = 0; $j < $this->col; ++$j) {
                if ($this->board[$i][$j] == '+')
                {
                    $this->flag = !$this->flag;
                    return 1;
                }
            }
        }

        return 3;
    }

    public function win()
    {
        if ($this->flag)
            printf("\033[%d;1H黑方羸!\n", $this->row + 2);
        else
            printf("\033[%d;1H白方羸!\n", $this->row + 2);
        printf("是否重来(Y/N):");
        $ch = ord(fgetc(STDIN));
        if ($ch == ord('Y') || $ch == ord('y')) {
            printf("\033[2J");
            $this->init();
            $this->show();
        } else
            $this->quit = FALSE;
    }

    public function he()
    {
        printf("\033[%d;1H和棋!\n", $this->row + 2);
        $this->quit = FALSE;
    }

    public function handle()
    {
        $ret = $this->press();

        if ($ret > 0 && $ret <= 3)
        {
            $this->show();
            if ($ret == 2)
                $this->win();
            else if ($ret == 3)
                $this->he();

            return true;
        }

        return false;
    }

    public function run()
    {
        system("stty -echo -icanon");

        while ($this->quit)
        {
            $ch = ord(fgetc(STDIN));
            if ($ch == 27)
                break;
            else if ($ch == ord('w')) {
                if ($this->r > 0)
                    $this->r--;
            }
            else if ($ch == ord('s')) {
                if ($this->r < $this->row - 1)
                    $this->r++;
            }
            else if ($ch == ord('a')) {
                if ($this->c > 0)
                    $this->c--;
            }
            else if ($ch == ord('d')) {
                if ($this->c < $this->col - 1)
                    $this->c++;
            }
            else if ($ch == 32) {
                $this->handle();
            }
            printf("\033[%d;%dH", $this->r + 1, $this->c + 1);
            // printf("\033[s\033[%d;1H\033[2Kr = %d, c = %d\033[u", $this->row + 1, $this->r, $this->c);
        }

        system("stty echo icanon");
        printf("\033[%d;1H", $this->row + 3);
    }
}

/*
 * printf("\033[2J");
 * $chess = new chess(5, 5);
 * $chess->run();
 */

